// Mutant Y^3 // (define "Score" (if (or // majority (< (/ 2) (count Pieces of:#1 in:(forEach of:(difference (sites {0..}) (sites {})) (sites {(+ (* (/ #2 )) (site))}) ))) (and (= 3 (count Pieces of:#1 in:(forEach of:(difference (sites {0..}) (sites {})) (sites {(+ (* (/ #2 )) (site))}) ))) (is Connected 3 at:(regionSite (intersection (sites Occupied by:(player #1)) (forEach of:(difference (sites {0..}) (sites {})) (sites {(+ (* (/ #2 )) (site))}) )) index:0 ) { (forEach of:(sites ) (sites {(+ (* (/ #2 )) (site))}) ) (forEach of:(sites ) (sites {(+ (* (/ #2 )) (site))}) ) (forEach of:(sites ) (sites {(+ (* (/ #2 )) (site))}) ) } ))) (set Var #4 (+ #3 (/ #2 )) (then (if (!= #1 (who at:(var #4))) (and (remove (var #4)) (add (piece #1) (to (var #4) // (apply (remove (to))) ) #5 ))))) (set Var #4 (+ #3 (/ #2 )) (then (if (= #1 (who at:(var #4))) (remove (var #4) #5 )))))) (define "ScoreThePiece" ("Score" #1 (var "L3") "ABoard" "L2" (then ("Score" #1 (var "L2") "ABoard" "L1" (then ("Score" #1 (var "L1") "ABoard" "L0" ) ))))) (define "LHTwistFrom" (% (+ { (% (/ #1 "ATri2") "ATri") (* (% #1 "ATri2") "ATri") (* (+ 1 (/ #1 "ATri3")) "ATri3") } ) "ABoard" )) (define "RHTwistFrom" (% (+ { (% (/ #1 "ATri") "ATri2") (* (% #1 "ATri") "ATri2") (* (+ 2 (/ #1 "ATri3")) "ATri3") } ) "ABoard" )) (define "ScorePlayers" (and (set Score P1 (+ { (count Pieces P1 in:(forEach (sites Board) if:(<= "ABoard" (site)))) (* 99 (count Pieces P1 in:(forEach (sites Board) if:(<= (+ "ABoard" (* 3 "ATri2")) (site))))) (* 900 (count Pieces P1 in:)) } )) (set Score P2 (+ { (count Pieces P2 in:(forEach (sites Board) if:(<= "ABoard" (site)))) (* 99 (count Pieces P2 in:(forEach (sites Board) if:(<= (+ "ABoard" (* 3 "ATri2")) (site))))) (* 900 (count Pieces P2 in:)) } )))) (define "AddToEmpty" (move Select (from (forEach (sites Empty) if:(> "ABoard" (site)))) (then (and { (add (piece #1) (to (last To) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" #1))) (add (piece #1) (to ("LHTwistFrom" (last To)) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" #1))) (add (piece #1) (to ("RHTwistFrom" (last To)) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" #1))) } #2 )))) (define "AlternatingMoves" ("AddToEmpty" (mover) (then "ScorePlayers"))) (define "FriendEnemyMoves" (if ("SameTurn") ("AddToEmpty" (next) (then "ScorePlayers")) ("AddToEmpty" (mover) (then (moveAgain))) )) (define "DoubleMoves" (if (or "SameTurn" (gt 0 (counter))) ("AddToEmpty" (mover) (then "ScorePlayers")) ("AddToEmpty" (mover) (then (moveAgain))) )) (define "SameIslandSites" (intersection (union { (sites Distance Adjacent from:(from) (range 1 3)) // Ludii bug: doesn't reach the lower left diagonal corner. (sites Distance Adjacent from:("LHTwistFrom" (from)) (range 1 3)) (sites Distance Adjacent from:("RHTwistFrom" (from)) (range 1 3)) } ) (sites Empty) )) (define "FireAndIceMoves" // (> "ABoard" (site)) (if (no Pieces Mover) ("AddToEmpty" (next) (then "ScorePlayers")) (move Select (from (forEach (sites Occupied by:Mover) if:#1)) (to (forEach of:"SameIslandSites" (sites { (site) ("LHTwistFrom" (site)) ("RHTwistFrom" (site)) } ))) (then (do (add (piece (next)) (to (last From) (apply (and (set Var "L3" (to)) (remove (to))))) (then (and ("ScoreThePiece" (mover)) ("ScoreThePiece" (next)))) ) next:(do (add (piece (next)) (to ("LHTwistFrom" (last From)) (apply (and (set Var "L3" (to)) (remove (to))))) (then (and ("ScoreThePiece" (mover)) ("ScoreThePiece" (next)))) ) next:(do (add (piece (next)) (to ("RHTwistFrom" (last From)) (apply (and (set Var "L3" (to)) (remove (to)))) ) (then (and ("ScoreThePiece" (mover)) ("ScoreThePiece" (next)))) ) // add 'to' must come after the 'from' replacements to ensure score updates correctly. next:(do (add (piece (mover)) (to (last To) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" (mover))) ) next:(do (add (piece (mover)) (to ("LHTwistFrom" (last To)) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" (mover))) ) next:(add (piece (mover)) (to ("RHTwistFrom" (last To)) (apply (set Var "L3" (to)))) (then ("ScoreThePiece" (mover))) )))))))) #2 )) (define "DoubleFireAndIceMoves" (if (or "SameTurn" (gt 0 (counter))) ("FireAndIceMoves" #1 (then "ScorePlayers")) ("FireAndIceMoves" (> "ABoard" (site)) (then (and "ScorePlayers" (moveAgain)))) )) //--------------------------------------------- // Main routine (game "Mutant Y^3" (players 2) (equipment { (board ("FractalBoard" ) use:Cell) (piece "Ball" Each ) } ) (rules (play ) (end { (if (< 1 (count Pieces P1 in:)) (byScore ) ) (if (< 1 (count Pieces P2 in:)) (byScore ) ) } ))) //------------------------------------------------- // Options (option "Protocol" args:{ } { (item "Alternating" <("AlternatingMoves")> "Turns alternate") (item "Turns (FE)*" <("FriendEnemyMoves")> "Turns follow (FE)* protocol: Each player places a Friend then places an Enemy.") (item "Turns 12*" <("DoubleMoves")> "Turns follow 12* protocol:Firs player places a piece then players alternate placing 2 pieces.") (item "Fire and Ice Moves" <("FireAndIceMoves" (> "ABoard" (site)) (then "ScorePlayers"))> "Fire and Ice Moves") (item "F-Ice Double Moves" <("DoubleFireAndIceMoves" (> "ABoard" (site)) (then "ScorePlayers"))> "Fire and Ice Moves") (item "F-Ice same piece twice" <("DoubleFireAndIceMoves" (= (last To) (site)) (then "ScorePlayers"))> "Fire and Ice Moves") } ) (option "Winning" args:{